package ijen.fbconnect;

import java.util.Properties;
import java.util.Date;
import java.io.FileOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.FileInputStream;

/**
 * Description of FB.
 * ---------------------------------------------------------------------------------------
 * User: fred
 * Date: Jul 22, 2009
 * Time: 12:07:36 PM
 * ---------------------------------------------------------------------------------------
 */
public final class FBSession {

    public enum Status {
        INVALID, UNCHECKED, EXPIRED, RESUMED
    }

    private static final String FBCONNECT_SESS_FILE = "FBConnectSession.xml";
    //private static final String N_DID_LOGIN = "FBConnect/didLogin";

    private String apiKey;
    private String applicationSecret;
    private String sessionSecret;
    private String sessionKey;
    private String userId;
    private long expires;
    private Status status;

    private static final FBSession INSTANCE;

    static {
        INSTANCE = new FBSession();
    }

    private FBSession() {
        expires = -1;
        status = Status.INVALID;
    }

    public static FBSession getInstance() {
        return INSTANCE;
    }

    /**
     * <p>Configure the shared session with API and application secret key
     * @param pApiKey  Application key (API key)
     * @param pSecret  Secret application key
     */
    public void init(final String pApiKey, final String pSecret) {
        assert pApiKey != null;

        INSTANCE.apiKey = pApiKey;
        INSTANCE.applicationSecret = pSecret;

        status = Status.UNCHECKED;
    }


    /**
     * <p>Start a new session with all its composant
     * @param pUid Facebook user id
     * @param pSessionKey Session key
     * @param pSessionSecret Session secret key
     * @param pExpires Expiration date (0 if inifinite session)
     */
    public void start(final String pUid, final String pSessionKey, final String pSessionSecret, final long pExpires) {

        long now = new Date().getTime();
        long expirationDate = pExpires * 1000;
        Date ed = new Date(expirationDate);

        if (now < expirationDate || pExpires == 0) {

            userId = pUid;
            sessionKey = pSessionKey;
            sessionSecret = pSessionSecret;
            expires = pExpires;

            System.out.printf(
                    expires == 0 ? "Session resumed (infinite session)\n" : ("Session resumed, expires on: %s\n"),
                    ed);

            status = Status.RESUMED;

        }  else {

            status = Status.EXPIRED;

            System.out.printf("Session expired on %s! User must login\n", ed);
        }
    }


    /**
     * <p>Send a fully configured request.
     * @param pRequest A FBRequest
     */
    public void send(final FBRequest pRequest) {
        pRequest.call();
    }


    /**
     * <p>Save session data on disk.
     */
    public void save() {

        if (sessionKey != null) {

            Properties props = new Properties();
            props.setProperty("FBUserId", userId);
            props.setProperty("FBSessionKey", sessionKey);
            props.setProperty("FBSessionSecret", sessionSecret);
            props.setProperty("FBSessionExpires", "" + expires);

            FileOutputStream fos = null;

            try {
                fos = new FileOutputStream(new File(FBCONNECT_SESS_FILE));
                props.storeToXML(fos, "FBConnect session file");
            } catch (IOException e) {
                throw new RuntimeException("Could not save session file", e);
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } catch (IOException e) {
                        e.printStackTrace();  // Trace only ...
                    }
                }
            }
        }

    }


    /**
     * <p>Load session data from disk
     */
    public void load() {
        Properties props = new Properties();
        FileInputStream fis = null;

        try {
            fis = new FileInputStream(new File(FBCONNECT_SESS_FILE));
            props.loadFromXML(fis);
        } catch (IOException e) {
            throw new RuntimeException("Could not load session file", e);
        } finally {
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();  // Trace only ...
                }
            }
        }

        start(  props.getProperty("FBUserId"),
                props.getProperty("FBSessionKey"),
                props.getProperty("FBSessionSecret"),
                Long.parseLong(props.getProperty("FBSessionExpires"))
        );

    }

    /*  -- Getters - setters -- */

    public boolean isConnected() {
        return sessionKey != null;  // Key might not be valid though ...
    }

    public String getApiKey() {
        return apiKey;
    }

    public String getSessionKey() {
        return sessionKey;
    }

    public String getSessionSecret() {
        return sessionSecret;
    }

    public String getApplicationSecret() {
        return applicationSecret;
    }

    public Status getStatus() {
        return status;
    }
}
